package com.atjava.nebula.core.service.impl;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import com.atjava.nebula.core.dao.ibatis.Condition;
import com.atjava.nebula.core.dao.ibatis.projection.IProjection;
import com.atjava.nebula.core.exception.baseExp.BusinessException;
import com.atjava.nebula.core.model.BaseModel;
import com.atjava.nebula.core.page.Page;
import com.atjava.nebula.core.service.BaseService;
import com.atjava.nebula.core.service.GenericService;
import com.atjava.nebula.core.service.InterceptService;
import com.atjava.nebula.core.util.context.SpringContextHolder;
import com.atjava.nebula.core.util.generic.GenericsUtils;

/**泛型Service的实现
 * @author kyo
 *
 * @param <T> 所要操作的实体类
 * @param <ID> 实体类的主键
 */
public class GenericServiceImpl<T extends BaseModel,ID extends Serializable>  implements GenericService<T,ID>{

	protected BaseService baseService;
	protected Class<T> entityClass;
	protected InterceptService intercept;
    /**构造方法
     * <br>
     *（ 默认使用主数据源）
     * 
     */
    @SuppressWarnings("unchecked")
	protected GenericServiceImpl() {
    	entityClass = (Class<T>) GenericsUtils.getSuperClassGenricType(getClass());
    	baseService = SpringContextHolder.getBean(BaseServiceImpl.class);
    		//(BaseServiceImpl)SpringBeanFactory.getBean("baseManager");
    }
    
	
	/**构造方法，需传入实体类
	 * <br>
	 * (由于无法直接取得当前类的泛型类型，所以需要把实体类传入)
	 * @param entityClass 实体类
	 */
	public GenericServiceImpl(Class<T> entityClass) {
    	this.entityClass = entityClass;
    	baseService = SpringContextHolder.getBean(BaseServiceImpl.class);
    }

	/**
	 * 取得entityClass.
	 * <p/>
	 * JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。
	 */
	protected Class<T> getEntityClass() {
		return entityClass;
	}

	/* 
	 * @see com.atjava.nebula.core.service.GenricService#ExecSql(java.lang.String)
	 */
	public List<Map<String,Object>> ExecSql(String sql) throws BusinessException {
		return baseService.ExecSql(sql);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#ExecSql(java.lang.String, java.lang.Object[])
	 */
	public List<Map<String, Object>> ExecSql(String sql, Object... params) throws BusinessException {
		return baseService.ExecSql(sql,params);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#create(com.atjava.nebula.core.model.BaseModel)
	 */
	public ID create(T o) throws BusinessException {
		//拦截
		before(o);
		ID id = baseService.create(o);
		//拦截
		after(o);
		return id;
	}


	/* 
	 * @see com.atjava.nebula.core.service.GenricService#getAll()
	 */
	public List<T> getAll() throws BusinessException {
		return baseService.getAll(entityClass);
	}


	/* 
	 * @see com.atjava.nebula.core.service.GenricService#getById(java.io.Serializable)
	 */
	public T getById(ID id) throws BusinessException {
		this.before(id);
		T t = baseService.getById(entityClass,id);
		this.after(id);
		return t;
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#count()
	 */
	public Integer count() throws BusinessException {
		return baseService.count(entityClass);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#count(com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public Integer count(Condition cond) throws BusinessException {
		return baseService.count(entityClass, cond);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#count(com.atjava.nebula.core.model.BaseModel)
	 */
	public Integer count(T obj) throws BusinessException {
		return baseService.count(obj);
	}
	
	/* 
	 * @see com.atjava.nebula.core.service.GenericService#count(com.atjava.nebula.core.dao.ibatis.projection.IProjection, com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public Integer count(IProjection projection, Condition cond) throws BusinessException {
		return baseService.count(entityClass,projection ,cond);
	}

	/* 
	 * @see com.atjava.nebula.core.service.GenericService#count(com.atjava.nebula.core.model.BaseModel, com.atjava.nebula.core.dao.ibatis.projection.IProjection)
	 */
	public Integer count(T obj, IProjection projection) throws BusinessException {
		return baseService.count(obj,projection );
	}	
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#list(com.atjava.nebula.core.model.BaseModel)
	 */
	public List<T> list(T obj) throws BusinessException {
		return baseService.list(obj);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#list(com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public List<T> list(Condition cond) throws BusinessException {
		return baseService.list(entityClass, cond);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#list(com.atjava.nebula.core.dao.ibatis.projection1.IProjection, com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public List<Map<String, Object>> list(IProjection projection, Condition cond) throws BusinessException {
		return baseService.list(entityClass, projection, cond);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#list(com.atjava.nebula.core.model.BaseModel, com.atjava.nebula.core.dao.ibatis.projection1.IProjection)
	 */
	public List<Map<String, Object>> list(T obj, IProjection projection) throws BusinessException {
		return baseService.list(obj, projection);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#page(com.atjava.nebula.core.model.BaseModel, int, int)
	 */
	public Page<T> page(T obj, int pageNo, int pageSize) throws BusinessException {
		return baseService.page(obj, pageNo, pageSize);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#page(com.atjava.nebula.core.dao.ibatis.Condition, int, int)
	 */
	public Page<T> page(Condition cond, int pageNo, int pageSize) throws BusinessException {
		return baseService.page(entityClass, cond, pageNo, pageSize);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#page(com.atjava.nebula.core.dao.ibatis.projection1.IProjection, com.atjava.nebula.core.dao.ibatis.Condition, int, int)
	 */
	public Page<Map<String, Object>> page(IProjection projection, Condition cond, int pageNo, int pageSize) throws BusinessException {
		return baseService.page(entityClass, projection, cond, pageNo, pageSize);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#page(com.atjava.nebula.core.model.BaseModel, com.atjava.nebula.core.dao.ibatis.projection1.IProjection, int, int)
	 */
	public Page<Map<String, Object>> page(T obj, IProjection projection, int pageNo, int pageSize) throws BusinessException {
		return baseService.page(obj, projection, pageNo, pageSize);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#remove(com.atjava.nebula.core.model.BaseModel)
	 */
	public void remove(T obj) throws BusinessException {
		this.before(obj);
		baseService.remove(obj);
		this.after(obj);
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#removeById(java.io.Serializable)
	 */
	public void removeById(ID id) throws BusinessException {
		this.before(entityClass, id);
		baseService.removeById(entityClass, id);
		this.after(entityClass, id);
		
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenricService#updateById(com.atjava.nebula.core.model.BaseModel)
	 */
	public void updateById(T obj) throws BusinessException {
		this.before(obj);
		baseService.updateById(obj);
		this.after(obj);
		
	}
	/* 
	 * @see com.atjava.nebula.core.service.GenericService#updateAllById(com.atjava.nebula.core.model.BaseModel)
	 */
	public void updateAllById(T obj) throws BusinessException {
		this.before(obj);
		baseService.updateAllById(obj);
		this.after(obj);
		
	}
	
	public InterceptService getIntercept() {
		return intercept;
	}

	public void setIntercept(InterceptService intercept) {
		this.intercept = intercept;
		this.intercept.setService((GenericService<T, ID>) this);
		startIntercept = true;
	}
	
	public void startIntercept(boolean flag){
		startIntercept = flag;
	}
	
	private boolean startIntercept = false;
	
	/**
	 * 执行前
	 * @param o
	 * @throws BusinessException
	 */
	private void before(Object...o) throws BusinessException{
		if(getIntercept() != null && startIntercept){
			getIntercept().before(o);
		}
	}
	
	/**
	 * 执行后
	 * @param o
	 * @throws BusinessException
	 */
	private void after(Object...o) throws BusinessException{
		if(getIntercept() != null && startIntercept){
			getIntercept().after(o);
		}
	}
}